/***********************************************************************************
 *FileName:  nsm3012.c
 *Author:    ChenJiehong
 *Version:   V1.0
 *Date:      2024-04-23
 ****************************************Includes************************************/
#include "nsm3012.h"

/***************************************Variables***********************************/

/***************************************Functions***********************************/

void NSM3012_Init(void)
{
	SPI_InitTypeDef SPI_InitStruct;

	RCC_APBPeriphClockCmd(RCC_APBPeriph_SPI, ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIO, ENABLE);

	/* SPI NSS */
	GPIO_PinAFConfig(GPIO_PinSource0, GPIO0_AF_IO_OUT);
	GPIO_OutTypeConfig(GPIO_Pin_0, GPIO_OType_PP);

	/* SPI CLK */
	GPIO_PinAFConfig(GPIO_PinSource1, GPIO1_AF_SPI_CLK);

	/* SPI 3Wire DATA */
	GPIO_PinAFConfig(GPIO_PinSource2, GPIO2_AF_SPI_MOSI);
	GPIO_PuPdConfig(GPIO_Pin_2, GPIO_PuPd_UP);

	SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
	SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
	SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStruct.SPI_WMode = SPI_WMode_3Wire;
	SPI_InitStruct.SPI_Direction = SPI_Direction_TX;
	SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
	SPI_InitStruct.SPI_TXFIFOThreshold = 4;
	SPI_InitStruct.SPI_RXFIFOThreshold = 4;

	SPI_Init(SPI, &SPI_InitStruct);

	SPI_Cmd(SPI, ENABLE);
}

uint8_t NSM3012_CalcCrc(uint8_t *ptr, uint8_t len)
{
	uint8_t i;
	uint8_t crc = 0x00;
	while (len--)
	{
		crc ^= *ptr++;
		for (i = 8; i > 0; --i)
		{
			if (crc & 0x80)
			{
				crc = (crc << 1) ^ crc_mul;
			}
			else
			{
				crc = (crc << 1);
			}
		}
	}
	return crc;
}

void NSM3012_WriteBytes(uint8_t *u8Data, uint8_t u8Len)
{
	SPI_SetTransceiverMode(SPI, SPI_Direction_TX);
	for (uint8_t i = 0; i < u8Len; i++)
	{
		SPI_SendData(SPI, u8Data[i]);
	}
	while (SPI_GetFlagStatus(SPI, SPI_FLAG_BUSY) != RESET)
		;
}

void NSM3012_ReadBytes(uint8_t *u8Data, uint8_t u8Len)
{
	SPI_SetTransceiverMode(SPI, SPI_Direction_RX);
	for (uint8_t i = 0; i < u8Len; i++)
	{
		SPI_SendData(SPI, 0);
	}
	while (SPI_GetFlagStatus(SPI, SPI_FLAG_BUSY) != RESET)
		;

	for (uint8_t i = 0; i < u8Len; i++)
	{
		u8Data[i] = SPI_ReceiveData(SPI);
	}
}

bool NSM3012_ReadAngl(NSM3012_Angle_Status_t *NSM3012_Angle_Status)
{
	bool ret = false;
	uint8_t u8Data[2] = {0xE0, 0X09};

	GPIO_ResetBits(GPIO_Pin_0);

	NSM3012_WriteBytes(u8Data, 2);
	NSM3012_ReadBytes((uint8_t *)NSM3012_Angle_Status, 4);
	GPIO_SetBits(GPIO_Pin_0);

	/* 角度更新完毕 */
	if ((NSM3012_Angle_Status->Status & 0x80) != 0)
	{
		u8Data[1] = NSM3012_Angle_Status->Angle & 0xFF;
		u8Data[0] = (NSM3012_Angle_Status->Angle >> 8) & 0xFF;
		if (NSM3012_CalcCrc(u8Data, 2) == NSM3012_Angle_Status->CRC)
		{
			ret = true;
		}
	}
	return ret;
}

/***************************************END OF FILE*********************************/
